﻿//-----------------------------------------------------------------------
// <copyright file="PersonController.cs" company="OverrideThis">
//     Copyright (c) 2010 OverrideThis.com
// </copyright>
//-----------------------------------------------------------------------
namespace OverrideThis.ContactManager.WebSite.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel.Syndication;
    using System.Text;
    using System.Web.Mvc;
    using System.Xml;
    using OverrideThis.ContactManager.Domain;
    using OverrideThis.ContactManager.WebSite.Helpers;
    using OverrideThis.ContactManager.WebSite.Infrastructure;
    using OverrideThis.ContactManager.WebSite.Infrastructure.ActionFilters;
    using OverrideThis.ContactManager.WebSite.Infrastructure.ActionResults;
    using OverrideThis.ContactManager.WebSite.Models;
    using OverrideThis.Core.Infrastucture.Mapper;
    using OverrideThis.Core.Infrastucture.Repository;
    using DependencyFactory = StructureMap.ObjectFactory;

    public class PersonController : Controller
    {
        private readonly IRepository repository;
        private readonly IMapper mapper;

        public PersonController(IRepository repository, IMapper mapper)
        {
            this.repository = repository;
            this.mapper = mapper;
        }
        
        [OutputFormat]
        [LogExecution]
        [OutputCache(Duration = 30, VaryByParam = "*")]
        public ActionResult Index(int? id)
        {
            var persons = this.repository.Get<Person>()
                .OrderBy(o => o.Lastname);
            var model = this.mapper
                .Map<IEnumerable<Person>, PersonListViewModel>(persons);
            model.SelectedPersonId = id ?? 0;
            return this.View(model);
        }

        public ActionResult Detail(int id)
        {
            var person = this.repository.Get<Person>()
                .First(p => p.Id == id);
            var model = this.mapper
                .Map<Person, PersonViewModel>(person);
            return View(model);
        }

        public ActionResult Rss()
        {
            var persons = this.repository.Get<Person>()
                .OrderBy(o => o.Lastname)
                .ToList();

            return new RssActionResult<Person>(new Uri(AppGlobalConstants.BASE_SERVER_URI + Url.Action("Index")),
                "Contact Manager (Feed)",
                "Person and Contacts",
                persons,
                p => p.Lastname + ", " + p.Firstname,
                p => String.Concat(p.Contacts.Select(c => c.Description + ", ")),
                p => new Uri(AppGlobalConstants.BASE_SERVER_URI + Url.Action("Detail", new { id = p.Id })));
        }

        public ActionResult Xml()
        {
            var persons = this.repository.Get<Person>()
                .OrderBy(o => o.Lastname);
            var model = this.mapper
                .Map<IEnumerable<Person>, PersonViewModel[]>(persons);
            return new XmlActionResult(model);
        }

        public ActionResult Birthdate(int day, int month, int year)
        {
            var persons = this.repository.Get<Person>()
                .Where(p => p.BirthDate == new DateTime(year, month, day))
                .OrderBy(o => o.Lastname);
            var model = this.mapper
                .Map<IEnumerable<Person>, PersonListViewModel>(persons);
            model.SelectedPersonId = 0;
            return View("Index", model);
        }

        [HttpGet]
        public ActionResult Create()
        {
            return this.View(
                this.mapper
                    .Map<PersonEditViewModel, PersonEditViewModel>(new PersonEditViewModel())
                );
        }

        [HttpPost]
        public ActionResult Create(PersonEditViewModel model)
        {
            if(ModelState.IsValid)
            {
                this.repository
                    .WithTransaction(
                        r => r.SaveOrUpdate(
                                new Person 
                                {
                                    Lastname = model.Lastname,
                                    Firstname = model.Firstname,
                                    BirthDate = model.BirthDate.Value,
                                    Country = (Country)Enum.Parse(typeof(Country), model.CountryDescription)
                                })
                    );
                return this.RedirectToAction("Index");
            }
            return this.View(this.mapper.Map<PersonEditViewModel, PersonEditViewModel>(model));
        }

        [HttpGet]
        public ActionResult Edit(int id)
        {
            var person = this.repository.Get<Person>()
                .FirstOrDefault(p => p.Id == id);
            if (person == null)
                return this.RedirectToAction("Index");
            return this.View(this.mapper.Map<Person, PersonEditViewModel>(person));
        }

        [HttpPost]
        public ActionResult Edit(PersonEditViewModel model)
        {
            if (ModelState.IsValid)
            {
                var person = this.repository.Get<Person>().First(p => p.Id == model.Id);
                person.Lastname = model.Lastname;
                person.Firstname = model.Firstname;
                person.BirthDate = model.BirthDate.Value;
                person.Country = (Country) Enum.Parse(typeof(Country), model.CountryDescription);
                this.repository.WithTransaction(r => r.SaveOrUpdate(person));
                return this.RedirectToAction("Index");
            }
            return this.View(this.mapper.Map<PersonEditViewModel, PersonEditViewModel>(model));
        }

    }
}
